VFG.VModel = function(viewer,option) {
	this.option = Cesium.defaultValue(option, Cesium.defaultValue.EMPTY_OBJECT);
	this.viewer = Cesium.defaultValue(viewer, undefined);
	if (!viewer) {
		console.log('viewer参数必填!');
		return;
	}
	if (!option) {
		console.log('参数必填!');return;
	}
	
	if(!option.model || !option.model.type=='OBJ' ){
		console.log('参数必填!');return;
	}
	
	
	this.option=option;
	this.primitive;
	this.videoEle;
	
	this.vertices=[];
	this.normals=[];
	this.colors=[];
	this.uvs=[];
	
	this.geometry={
		vertices: [],
		normals: [],
		colors: [],
		uvs: [],
		indices:[],
	}
	this.init();
}

VFG.VModel.prototype.init=function(){
	this.read();
}

VFG.VModel.prototype.read=function(){
	var _this=this;
	var request = new XMLHttpRequest();
	request.onreadystatechange = function() {
		if (request.readyState == 4 && request.status != 404) {
			if(_this.option.onsuccess){
			}
			_this.parse(request.responseText);
			_this.create(_this.geometry);
		}
	};
	request.onerror=function(error){
		if(_this.option.onerror){
			_this.option.onerror(error)
		}
	};
	request.ontimeout=function(error){
		if(_this.option.ontimeout){
			_this.option.ontimeout(error)
		}
	};
	
	if('1' ==_this.option.model.isRelUrl){
		request.open('GET', _this.option.localUrl+_this.option.model.url, true); 
	}else{
		request.open('GET', _this.option.model.url, true); 
	}
	request.send();
}

VFG.VModel.prototype.create=function(geometry){
	var _this=this;
	var normals=geometry.normals;
	var uvs=geometry.uvs;
	var vertices=geometry.vertices;
	var indices=new Uint16Array(geometry.indices);
	
    this.primitive=_this.viewer.scene.primitives.add(new Cesium.Primitive({
        geometryInstances: new Cesium.GeometryInstance({
            geometry: new Cesium.Geometry({
                attributes: {
                    position: new Cesium.GeometryAttribute({
                        componentDatatype: Cesium.ComponentDatatype.DOUBLE,
                        componentsPerAttribute: 3,
                        values: vertices
                    }),
                    normal: new Cesium.GeometryAttribute({
                        componentDatatype: Cesium.ComponentDatatype.FLOAT,
                        componentsPerAttribute: 3,
                        values: normals
                    }),
                    st: new Cesium.GeometryAttribute({
                        componentDatatype: Cesium.ComponentDatatype.FLOAT,
                        componentsPerAttribute: 2,
                        values: uvs
                    }),
                },
               // indices: indices, 
                id:_this.option,
                primitiveType: Cesium.PrimitiveType.TRIANGLES,
                boundingSphere: Cesium.BoundingSphere.fromVertices(vertices),
            }),
        }),
       appearance: new Cesium.MaterialAppearance({
/*            material: new Cesium.Material({ 
	     	     fabric : {
	     		    type : 'Image',
	     		    uniforms : {
	     		      image : _this.option.imgUrl
	     		    }
	     		  }
     		}),*/
    	    material: _this.getMaterial(),
            faceForward : true, 
            closed: false 
        }),
        modelMatrix: _this.getModelMatrix(),
        asynchronous: false
    }));
}

VFG.VModel.prototype.getMaterial = function() {
	var _self = this;
	if(_self.option.video){
		_self.videoEle=_self.createVideoEle();
		_self.canplaythrough=function () {
	    	_self.viewer.clock.onTick.addEventListener(_self.activeVideoListener, _self);
	    };
	    _self.videoEle.addEventListener("canplaythrough",_self.canplaythrough );
	    var material = Cesium.Material.fromType('Image');
	    material.uniforms.image =_self.videoEle;
	    return material;
	}else{
		return new Cesium.Material({
		    fabric : {
		        type : 'Color',
		        uniforms : {
		            color : Cesium.Color.BLACK.withAlpha(0.5)
		        }
		    }
		})
	}
};

VFG.VModel.prototype.createVideoEle = function () {
	var _self = this;
	 var r = document.createElement("VIDEO");
	var src;
	if(_self.option.video && _self.option.video.type=='FILE'){
		src=_self.option.video.url;
	}
	else{
    	_self.webRtcServer= new WebRtcStreamer(r,_self.option.video.url);
	    _self.webRtcServer.connect(_self.option.video.id,'','');
	}
	this.videoId = "visualDomId"+_self.option.id;
    var t = document.createElement("SOURCE");
    t.type = "video/mp4",
    t.src = src;
    var i = document.createElement("SOURCE");
    i.type = "video/quicktime",
    i.src = src;
    return r.setAttribute("autoplay", !0),
    r.setAttribute("loop", !0),
    r.setAttribute("crossorigin", !0),
    r.setAttribute("muted", "muted"),
    r.appendChild(t),
    r.appendChild(i),
    r.style.display = "none",
    document.body.appendChild(r),
    r
}

VFG.VModel.prototype.update = function() {
	var _this = this;
	var modelMatrix=_this.getModelMatrix();
	if(this.primitive){
		this.primitive.modelMatrix=modelMatrix;
	}
};


VFG.VModel.prototype.parse=function( text ) {
	var _this=this;
	if ( text.indexOf( '\r\n' ) !== - 1 ) {
		text = text.replace( /\r\n/g, '\n' );
	}

	if ( text.indexOf( '\\\n' ) !== - 1 ) {
		text = text.replace( /\\\n/g, '' );
	}

	var lines = text.split( '\n' );
	var line = '', lineFirstChar = '';
	var lineLength = 0;
	var result = [];

	// Faster to just trim left side of the line. Use if available.
	var trimLeft = ( typeof ''.trimLeft === 'function' );

	for ( var i = 0, l = lines.length; i < l; i ++ ) {

		line = lines[ i ];
		line = trimLeft ? line.trimLeft() : line.trim();
		lineLength = line.length;
		if ( lineLength === 0 ) continue;

		lineFirstChar = line.charAt( 0 );
		// @todo invoke passed in handler if any
		if ( lineFirstChar === '#' ) continue;

		if ( lineFirstChar === 'v' ) {
			var data = line.split( /\s+/ );
			switch ( data[ 0 ] ) {
				case 'v':
					_this.vertices.push(
						parseFloat( data[ 1 ] ),
						parseFloat( data[ 2 ] ),
						parseFloat( data[ 3 ] )
					);
					if ( data.length >= 7 ) {
						_this.colors.push(
							parseFloat( data[ 4 ] ),
							parseFloat( data[ 5 ] ),
							parseFloat( data[ 6 ] )
						);
					} else {
						_this.colors.push( undefined, undefined, undefined );
					}
					break;
				case 'vn':
					_this.normals.push(
						parseFloat( data[ 1 ] ),
						parseFloat( data[ 2 ] ),
						parseFloat( data[ 3 ] )
					);
					break;
				case 'vt':
					_this.uvs.push(
						parseFloat( data[ 1 ] ),
						parseFloat( data[ 2 ] )
					);
					break;

			}

		} else if ( lineFirstChar === 'f' ) {
			var lineData = line.substr( 1 ).trim();
			var vertexData = lineData.split( /\s+/ );
			var faceVertices = [];

			// Parse the face vertex data into an easy to work with format
			for ( var j = 0, jl = vertexData.length; j < jl; j ++ ) {
				var vertex = vertexData[ j ];
				if ( vertex.length > 0 ) {
					var vertexParts = vertex.split( '/' );
					faceVertices.push( vertexParts );
					this.geometry.indices.push(vertexParts[0]*1-1);
				}
				
			}
			var v1 = faceVertices[ 0 ];
			for ( var j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) {
				var v2 = faceVertices[ j ];
				var v3 = faceVertices[ j + 1 ];
				_this.addFace(
					v1[ 0 ], v2[ 0 ], v3[ 0 ],
					v1[ 1 ], v2[ 1 ], v3[ 1 ],
					v1[ 2 ], v2[ 2 ], v3[ 2 ]
				);
			}
		} else {
			if ( line === '\0' ) continue;
		}
	}
}

VFG.VModel.prototype.getModelMatrix = function() {
	var _self = this;
	var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(_self.getPosition());
	var scaleMatrix = Cesium.Matrix4.fromScale(_self.getScale());
		modelMatrix = Cesium.Matrix4.multiply(modelMatrix, scaleMatrix, new Cesium.Matrix4());
	var hprRotation = Cesium.Matrix3.fromHeadingPitchRoll(_self.getRotation());
	var hpr = Cesium.Matrix4.fromRotationTranslation(hprRotation,new Cesium.Cartesian3(0.0, 0.0, 0.0));
	return Cesium.Matrix4.multiply(modelMatrix, hpr, modelMatrix);
}; 

VFG.VModel.prototype.getScale = function() {
	var _self = this;
	return new Cesium.Cartesian3(
			_self.option.scaleX?_self.option.scaleX*1:1,
			_self.option.scaleY?_self.option.scaleY*1:1,
			_self.option.scaleZ?_self.option.scaleZ*1:1);
};

VFG.VModel.prototype.addFace= function ( a, b, c, ua, ub, uc, na, nb, nc ) {
	var vLen = this.vertices.length;
	
	var ia = this.parseVertexIndex( a, vLen );
	var ib = this.parseVertexIndex( b, vLen );
	var ic = this.parseVertexIndex( c, vLen );

	this.addVertex( ia, ib, ic );
	this.addColor( ia, ib, ic );
	
	
	 this.geometry.indices.push(ia);
	 this.geometry.indices.push(ib);
	 this.geometry.indices.push(ic);
	

	// normals
	if ( na !== undefined && na !== '' ) {
		var nLen = this.normals.length;
		ia = this.parseNormalIndex( na, nLen );
		ib = this.parseNormalIndex( nb, nLen );
		ic = this.parseNormalIndex( nc, nLen );
		this.addNormal( ia, ib, ic );
	} else {
		this.addFaceNormal( ia, ib, ic );
	}

	// uvs
	if ( ua !== undefined && ua !== '' ) {
		var uvLen = this.uvs.length;
		ia = this.parseUVIndex( ua, uvLen );
		ib = this.parseUVIndex( ub, uvLen );
		ic = this.parseUVIndex( uc, uvLen );
		this.addUV( ia, ib, ic );
	} else {
		this.addDefaultUV();
	}
},

//use
VFG.VModel.prototype.addVertex=function ( a, b, c ) {
	var src = this.vertices;
	var dst = this.geometry.vertices;
	dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
	dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
	dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
},

//use
VFG.VModel.prototype.addNormal=function ( a, b, c ) {
	var src = this.normals;
	var dst = this.geometry.normals;
	dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
	dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
	dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
},

//use
VFG.VModel.prototype.addFaceNormal=function ( a, b, c ) {

	var src = this.vertices;
	var dst = this.geometry.normals;

	vA.fromArray( src, a );
	vB.fromArray( src, b );
	vC.fromArray( src, c );

	cb.subVectors( vC, vB );
	ab.subVectors( vA, vB );
	cb.cross( ab );

	cb.normalize();

	dst.push( cb.x, cb.y, cb.z );
	dst.push( cb.x, cb.y, cb.z );
	dst.push( cb.x, cb.y, cb.z );

},

//use
VFG.VModel.prototype.addColor= function ( a, b, c ) {

	var src = this.colors;
	var dst = this.geometry.colors;

	if ( src[ a ] !== undefined ) dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
	if ( src[ b ] !== undefined ) dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
	if ( src[ c ] !== undefined ) dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );

},

//use
VFG.VModel.prototype.addUV= function ( a, b, c ) {
	var src = this.uvs;
	var dst = this.geometry.uvs;
	dst.push( src[ a + 0 ], src[ a + 1 ] );
	dst.push( src[ b + 0 ], src[ b + 1 ] );
	dst.push( src[ c + 0 ], src[ c + 1 ] );
},

//use
VFG.VModel.prototype.addDefaultUV=function () {
	var dst = this.geometry.uvs;
	dst.push( 0, 0 );
	dst.push( 0, 0 );
	dst.push( 0, 0 );
},

VFG.VModel.prototype.parseVertexIndex=function ( value, len ) {
	var index = parseInt( value, 10 );
	return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
},

VFG.VModel.prototype.parseNormalIndex=function ( value, len ) {
	var index = parseInt( value, 10 );
	return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
},
VFG.VModel.prototype.parseUVIndex=function ( value, len ) {
	var index = parseInt( value, 10 );
	return ( index >= 0 ? index - 1 : index + len / 2 ) * 2;
},

VFG.VModel.prototype.getPosition = function() {
	var _self = this;
	return Cesium.Cartesian3.fromDegrees(_self.option.x*1,_self.option.y*1,_self.option.z*1);
};
VFG.VModel.prototype.getRotation = function() {
	var _self = this;
	return new Cesium.HeadingPitchRoll(
		Cesium.Math.toRadians(_self.option.rotationX?_self.option.rotationX*1:0), 
		Cesium.Math.toRadians(_self.option.rotationY?_self.option.rotationY*1:0), 
		Cesium.Math.toRadians(_self.option.rotationZ?_self.option.rotationZ*1:0));
};

VFG.VModel.prototype.activeVideoListener = function (e) {
	var _this=this;
    try {
        if (_this._videoPlay && _this.videoEle.paused) _this.videoEle.play();
    } catch (e) {}
}

VFG.VModel.prototype.deActiveVideo = function (e) {
	this.viewer.clock.onTick.removeEventListener(this.activeVideoListener, this);
}

VFG.VModel.prototype.destroy = function () {
  this.deActiveVideo();
  if(this.primitive){
	  this.viewer.scene.primitives.remove(this.primitive);
  }
  if(this.primitive){
	  this.viewer.scene.primitives.remove(this.primitive);
  }
  
  if(this.videoEle){
	  this.videoEle.removeEventListener('canplaythrough',this.canplaythrough);
  }
  if(this.webRtcServer){
	  this.webRtcServer.disconnect();
  }
  this.videoEle && this.videoEle.parentNode.removeChild(this.videoEle),
  delete this.webRtcServer,
  delete this.videoEle,
  delete this.options,
  delete this.viewer;
  return Cesium.destroyObject(this);
};
